/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * SimPanel.java
 *
 * Created on May 25, 2009, 9:46:44 AM
 */

package applications;

import analysis.SimulationLog;
import analysis.Statistics;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.UIManager;
import scio.coordinate.R2;
import scio.coordinate.R3;
import simulation.Simulation;
import specto.euclidean3.Axes3D;

/**
 *
 * @author ae3263
 */
public class SimPanel extends javax.swing.JPanel implements ActionListener {

    /** Creates new form SimPanel */
    public SimPanel() {
        try { UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) {}
        initComponents();

        setSimulation(sim);

        plot2D.getVisometry().setBounds(new R2(-70,-70),new R2(70,70));
        metricsPlot.getVisometry().setBounds(new R2(-10,-10),new R2(500,150));
        metricsPlot.synchronizeTimerWith(plot2D);
        plot3D.getVisometry().setTDir(new R3(-.28,.73,-.623));
        plot3D.getVisometry().setNDir(new R3(.9,.436,0));
        plot3D.getVisometry().setBDir(new R3(-.272,.561,.779));
        plot3D.getVisometry().setBounds(new R2(-200,-200),new R2(200,200));
        plot3D.getVisometry().setSceneSize(60);
        plot3D.getVisometry().setViewDist(100);
        plot3D.getVisometry().setClipDist(5.0);
        plot3D.synchronizeTimerWith(plot2D);

        plot2D.add(mainVisuals);
        metricsPlot.add(metricVisuals);
        metricsPlot.add(metricVisuals.getLegend(),5,2);
        plot3D.add(mainVisuals3D);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        sim = new simulation.Simulation();
        mainVisuals = new analysis.MainVisuals();
        mainVisuals3D = new analysis.MainVisuals3D();
        metricVisuals = new analysis.MetricVisuals();
        jSplitPane1 = new javax.swing.JSplitPane();
        jSplitPane2 = new javax.swing.JSplitPane();
        simSettingsPanel = new applications.SimulationSettingsPanel();
        JTabbedPane1 = new javax.swing.JTabbedPane();
        metricsPlot = new specto.euclidean2.Plot2D();
        jScrollPane1 = new javax.swing.JScrollPane();
        logArea = new javax.swing.JTextArea();
        jScrollPane2 = new javax.swing.JScrollPane();
        dataArea = new javax.swing.JTextArea();
        jTabbedPane2 = new javax.swing.JTabbedPane();
        plot2D = new specto.euclidean2.Plot2D();
        plot3D = new specto.euclidean3.Plot3D();

        jSplitPane1.setOneTouchExpandable(true);

        jSplitPane2.setDividerLocation(200);
        jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane2.setResizeWeight(1.0);
        jSplitPane2.setOneTouchExpandable(true);
        jSplitPane2.setTopComponent(simSettingsPanel);

        metricsPlot.setMarkerBoxVisible(false);
        metricsPlot.setAnimatorVisible(false);

        javax.swing.GroupLayout metricsPlotLayout = new javax.swing.GroupLayout(metricsPlot);
        metricsPlot.setLayout(metricsPlotLayout);
        metricsPlotLayout.setHorizontalGroup(
            metricsPlotLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 395, Short.MAX_VALUE)
        );
        metricsPlotLayout.setVerticalGroup(
            metricsPlotLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 196, Short.MAX_VALUE)
        );

        JTabbedPane1.addTab("Metrics", metricsPlot);

        logArea.setColumns(20);
        logArea.setRows(5);
        jScrollPane1.setViewportView(logArea);

        JTabbedPane1.addTab("Log", jScrollPane1);

        dataArea.setColumns(20);
        dataArea.setRows(5);
        jScrollPane2.setViewportView(dataArea);

        JTabbedPane1.addTab("Data", jScrollPane2);

        jSplitPane2.setRightComponent(JTabbedPane1);

        jSplitPane1.setLeftComponent(jSplitPane2);

        plot2D.setAxisStyle(1);
        plot2D.setMarkerBoxVisible(false);

        javax.swing.GroupLayout plot2DLayout = new javax.swing.GroupLayout(plot2D);
        plot2D.setLayout(plot2DLayout);
        plot2DLayout.setHorizontalGroup(
            plot2DLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 358, Short.MAX_VALUE)
        );
        plot2DLayout.setVerticalGroup(
            plot2DLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 402, Short.MAX_VALUE)
        );

        jTabbedPane2.addTab("2D View", plot2D);

        plot3D.setAxisStyle(Axes3D.AXES_TOPHALF);
        plot3D.setControlsVisible(false);
        plot3D.setZLabel("time");
        plot3D.setMarkerBoxVisible(false);
        plot3D.setViewBoxVisible(false);

        javax.swing.GroupLayout plot3DLayout = new javax.swing.GroupLayout(plot3D);
        plot3D.setLayout(plot3DLayout);
        plot3DLayout.setHorizontalGroup(
            plot3DLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 358, Short.MAX_VALUE)
        );
        plot3DLayout.setVerticalGroup(
            plot3DLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 402, Short.MAX_VALUE)
        );

        jTabbedPane2.addTab("3D View", plot3D);

        jSplitPane1.setRightComponent(jTabbedPane2);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 772, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 432, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTabbedPane JTabbedPane1;
    private javax.swing.JTextArea dataArea;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JSplitPane jSplitPane2;
    private javax.swing.JTabbedPane jTabbedPane2;
    private javax.swing.JTextArea logArea;
    private analysis.MainVisuals mainVisuals;
    private analysis.MainVisuals3D mainVisuals3D;
    private analysis.MetricVisuals metricVisuals;
    private specto.euclidean2.Plot2D metricsPlot;
    private specto.euclidean2.Plot2D plot2D;
    private specto.euclidean3.Plot3D plot3D;
    private simulation.Simulation sim;
    private applications.SimulationSettingsPanel simSettingsPanel;
    // End of variables declaration//GEN-END:variables

    public Simulation getSimulation() {
        return sim;
    }

    public void setSimulation(Simulation simulation1) {
        if (simulation1 == null) {
            return;
        }
        sim.removeActionListener(this);
        sim = simulation1;
        sim.addActionListener(this);
        mainVisuals.setSim(sim);
        metricVisuals.setSim(sim);
        mainVisuals3D.setSim(sim);
        rebuildMenus();
        sim.run();
    }

    public void redraw() {
        plot2D.repaint();
        plot3D.repaint();
        metricsPlot.repaint();
        simSettingsPanel.repaint();
    }

    public void rebuildMenus() {
        plot2D.rebuildOptionsMenu();
        plot3D.rebuildOptionsMenu();
        metricsPlot.rebuildOptionsMenu();
        simSettingsPanel.setTree(sim.ss);
    }

    public void animate() {
        plot2D.getTimer().start();
    }

    public void log(String string) {
        logArea.append(string+"\n");
    }

    public void actionPerformed(ActionEvent e) {
        String action = e.getActionCommand();
        if(action.equals("redraw")) {
            redraw();
        } else if (action.equals("reset")) {
            fireStatusMessage("Resetting simulation...");
            rebuildMenus();
        } else if (action.equals("update")) {
            fireStatusMessage("Updating simulation...");
            setSimulation(sim);
        } else if (action.equals("log")) {
            if(e.getSource() instanceof SimulationLog){
                ((SimulationLog)e.getSource()).output(logArea);
            }else if(e.getSource() instanceof Statistics){
                ((Statistics)e.getSource()).output(logArea);
                // copy stats to dataWindow and then to clipboard
                fireStatusMessage("Copying stats to clipboard...");
                ((Statistics)e.getSource()).outputData(dataArea);
                StringSelection data = new StringSelection(dataArea.getText());
                Toolkit.getDefaultToolkit().getSystemClipboard().setContents(data, data);
                fireStatusMessage("Success! The batch data has been copied to the clipboard.");
            }
        } else {
            log(action);
            fireStatusMessage(action);
        }
    }

    private void fireStatusMessage(String string) {
//        throw new UnsupportedOperationException("Not yet implemented");
    }


    void set3DItemsVisible(boolean state) {
        plot3D.setControlsVisible(state);
        plot3D.setViewBoxVisible(state);
        plot3D.repaint();
    }

    void setAnimationStyle(int style) {
        mainVisuals.setAnimationStyle(style);
        mainVisuals3D.setAnimationStyle(style);
        plot2D.repaint();
        plot3D.repaint();
    }

    void setAnimatorVisible(boolean state) {
        plot2D.setAnimatorVisible(state);
        plot3D.setAnimatorVisible(state);
        plot2D.repaint();
        plot3D.repaint();
    }

    void setMarkerBoxVisible(boolean state) {
        plot2D.setMarkerBoxVisible(state);
        plot3D.setMarkerBoxVisible(state);
        plot2D.repaint();
        plot3D.repaint();
    }

    void setNetworkVisible(boolean state) {
        mainVisuals.setNetworkVisible(state);
        plot2D.repaint();
    }

    void setPositionsVisible(boolean state) {
        mainVisuals.setPositionsVisible(state);
        mainVisuals3D.setPositionsVisible(state);
        plot2D.repaint();
        plot3D.repaint();
    }

    void setStartVisible(boolean state) {
        mainVisuals.setStartVisible(state);
        mainVisuals3D.setStartVisible(state);
        plot2D.repaint();
        plot3D.repaint();
    }
}
